package com.bifang.core.quartz.integration.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bifang.common.constant.enums.common.BoolEnum;
import com.bifang.common.constant.enums.common.FuncTypeEnum;
import com.bifang.common.exception.AppException;
import com.bifang.common.util.PagerUtil;
import com.bifang.common.vo.BaseVO;
import com.bifang.common.vo.QrtzDetailsVO;
import com.bifang.common.vo.QuartzVO;
import com.bifang.common.annotations.ApiService;
import com.bifang.common.annotations.OpApi;
import com.bifang.core.quartz.config.QuartzManager;
import com.bifang.core.dao.mapper.QrtzDetailsMapper;
import com.bifang.core.dao.model.QrtzDetails;
import com.bifang.core.dao.model.QrtzJobDetails;
import com.bifang.core.dao.service.QrtzJobDetailsService;
import com.bifang.core.quartz.integration.QuartzIntegration;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/***
 * 定时任务服务
 * */
@Service
@ApiService(funcCode = "QUARTZ", title = "定时任务服务")
public class QuartzIntegrationImpl implements QuartzIntegration {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired QuartzManager quartzManager;
    @Autowired QrtzDetailsMapper qrtzDetailsMapper;
    @Autowired QrtzJobDetailsService qrtzJobDetailsService;

    @Override
    @OpApi(
            funcCode = "QUARTZ0001",
            title = "获取定时任务详情",
            funcType = FuncTypeEnum.query,
            publicFlag = BoolEnum.TRUE,
            savelog = false)
    public QrtzDetailsVO getQuartzDetail(QrtzDetailsVO qrtzDetailsVO) {
        if (StringUtils.isBlank(qrtzDetailsVO.getJobName())) {
            throw new AppException("任务名称不能为空");
        }
        QrtzDetails query = new QrtzDetails();
        query.setJobName(qrtzDetailsVO.getJobName());
        query.setJobGroup(qrtzDetailsVO.getJobGroup());
        query.setSchedName(qrtzDetailsVO.getSchedName());
        List<QrtzDetails> qrtzList = qrtzDetailsMapper.selectByObject(query);
        if (CollectionUtils.isEmpty(qrtzList)) {
            throw new AppException("没有找到任务信息");
        }
        if (qrtzList.size() > 1) {
            throw new AppException("任务信息不唯一");
        }
        QrtzDetailsVO vo = Convert.convert(QrtzDetailsVO.class, qrtzList.get(0));
        QuartzVO quartzVO = Convert.convert(QuartzVO.class, vo);
        try {
            Map<String, Object> params = quartzManager.getJobParams(quartzVO);
            if (!CollectionUtils.isEmpty(params)) {
                vo.setParameter(JSONUtil.toJsonStr(params));
            }

        } catch (Exception e) {
            logger.error("获取参数失败", e);
        }

        return vo;
    }

    @Override
    @OpApi(
            funcCode = "QUARTZ0002",
            title = "获取定时任务列表",
            funcType = FuncTypeEnum.query,
            publicFlag = BoolEnum.TRUE,
            savelog = false)
    public PageInfo<QrtzDetailsVO> getQuartzList(QrtzDetailsVO qrtzDetailsVO) {
        if (qrtzDetailsVO.getPageNum() != null && qrtzDetailsVO.getPageSize() != null) {
            PageHelper.startPage(qrtzDetailsVO.getPageNum(), qrtzDetailsVO.getPageSize());
        }
        QrtzDetails query = Convert.convert(QrtzDetails.class, qrtzDetailsVO);
        List<QrtzDetails> qrtzList = qrtzDetailsMapper.selectByObject(query);
        if (CollectionUtils.isEmpty(qrtzList)) {
            return PagerUtil.createEmptyPagerInfo(
                    qrtzDetailsVO.getPageNum(), qrtzDetailsVO.getPageSize());
        }
        PageInfo<QrtzDetails> qrtzPageInfo = new PageInfo<>(qrtzList);
        List<QrtzDetailsVO> list = new ArrayList<>();
        for (QrtzDetails qrtzDetails : qrtzPageInfo.getList()) {
            QrtzDetailsVO vo = Convert.convert(QrtzDetailsVO.class, qrtzDetails);
            QuartzVO quartzVO = Convert.convert(QuartzVO.class, vo);
            try {
                Map<String, Object> params = quartzManager.getJobParams(quartzVO);
                if (!CollectionUtils.isEmpty(params)) {
                    vo.setParameter(JSONUtil.toJsonStr(params));
                }

            } catch (Exception e) {
                logger.error("获取参数失败", e);
            }
            list.add(vo);
        }
        return PagerUtil.parsePagerVo(list, qrtzPageInfo);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0003", title = "新增定时任务", funcType = FuncTypeEnum.insert)
    public QrtzDetailsVO addJob(QuartzVO quartzVO) {
        QueryWrapper<QrtzJobDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(QrtzJobDetails::getJobName, quartzVO.getJobName());
        List<QrtzJobDetails> list = qrtzJobDetailsService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            throw new AppException("任务名重复");
        }
        quartzManager.addJob(quartzVO);
        QrtzDetailsVO query = Convert.convert(QrtzDetailsVO.class, quartzVO);
        return getQuartzDetail(query);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0004", title = "修改定时任务", funcType = FuncTypeEnum.update)
    public QrtzDetailsVO updateJob(QuartzVO quartzVO) {
        QrtzDetailsVO query = Convert.convert(QrtzDetailsVO.class, quartzVO);
        QrtzDetailsVO oldJob = getQuartzDetail(query);
        if (!oldJob.getJobClassName().equals(quartzVO.getJobClassName())) {
            quartzManager.removeJob(quartzVO);
            quartzManager.addJob(quartzVO);
        } else {
            quartzManager.updateJob(quartzVO);
        }

        return getQuartzDetail(query);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0005", title = "删除定时任务", funcType = FuncTypeEnum.delete)
    public void deleteJob(QuartzVO quartzVO) {
        quartzManager.removeJob(quartzVO);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0006", title = "开始所有任务", funcType = FuncTypeEnum.other)
    public void startJobs(BaseVO baseVO) {
        quartzManager.startJobs();
    }

    @Override
    @OpApi(funcCode = "QUARTZ0007", title = "停止所有任务", funcType = FuncTypeEnum.other)
    public void shutdownJobs(BaseVO baseVO) {
        quartzManager.shutdownJobs();
    }

    @Override
    @OpApi(funcCode = "QUARTZ0008", title = "暂停所有任务", funcType = FuncTypeEnum.other)
    public void pauseAll(BaseVO baseVO) {
        quartzManager.pauseAll();
    }

    @Override
    @OpApi(funcCode = "QUARTZ0009", title = "恢复所有任务", funcType = FuncTypeEnum.other)
    public void resumeAll(BaseVO baseVO) {
        quartzManager.resumeAll();
    }

    @Override
    @OpApi(funcCode = "QUARTZ0010", title = "暂停某个任务", funcType = FuncTypeEnum.other)
    public QrtzDetailsVO pauseJob(QuartzVO quartzVO) {
        quartzManager.pauseJob(quartzVO);
        return getVO(quartzVO);
    }

    private QrtzDetailsVO getVO(QuartzVO quartzVO) {
        QrtzDetailsVO query = new QrtzDetailsVO();
        query.setSchedName(quartzVO.getSchedName());
        query.setJobName(quartzVO.getJobName());
        query.setJobGroup(quartzVO.getJobGroup());
        return getQuartzDetail(query);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0011", title = "恢复某个任务", funcType = FuncTypeEnum.other)
    public QrtzDetailsVO resumeJob(QuartzVO quartzVO) {
        quartzManager.resumeJob(quartzVO);
        return getVO(quartzVO);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0012", title = "立即执行一次任务", funcType = FuncTypeEnum.other)
    public QrtzDetailsVO triggerJob(QuartzVO quartzVO) {
        quartzManager.triggerJob(quartzVO);
        return getVO(quartzVO);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0013", title = "获取触发器当前状态", funcType = FuncTypeEnum.query)
    public String getTriggerState(QuartzVO quartzVO) {
        return quartzManager.getTriggerState(quartzVO);
    }

    @Override
    @OpApi(funcCode = "QUARTZ0014", title = "重置错误状态触发器", funcType = FuncTypeEnum.query)
    public QrtzDetailsVO resetTriggerFromErrorState(QuartzVO quartzVO) {
        quartzManager.resetTriggerFromErrorState(quartzVO);
        return getVO(quartzVO);
    }
}
